/*****************************************
 * Author:  huiaove
 * Email:   huiaove@126.com
 * Date:    2021 02.19
 * Address: TianJin
 * Version: V1.0.0
 * 修改记录：
 *             2021 02.19    张亚辉    JA协议V1.0               版本号:V1.0.0
 * 功能说明：JA 协议解析驱动
 * **************************************/
#include "JA_Protocol.h"
#include "CRC16.h"
#include "malloc.h"
/*************************************
 * 功能：创建JA协议解析
 * 参数：
 *         tcb：JA协议控制块
 *         *Parse:解析函数
 *         addr:协议地址
 *         buf:缓存区
 *         size：缓存大小
 * 返回：无
 * **********************************/
void JA_Create(JA_Protocol_TCB *tcb, JA_BytesArray (*Parse)(JA_Protocol, uint8_t *), uint8_t *buf, uint16_t size)
{
    tcb->Parse = Parse; //解析函数
    tcb->parse_pointer = 0;
    tcb->command_buf = buf;
    tcb->Buf_Size = size;
}

/*******************************
 * 功能：JA协议数据解码
 * 参数：
 *         *tcb:JA协议解析控制块
 *         data：需要解析的数据
 * ****************************/
JA_StatusTypeDef JA_Decode(JA_Protocol_TCB *tcb, uint8_t data, JA_BytesArray *reply_buf)
{
    JA_BytesArray r_buf;
    if (tcb->parse_pointer == 0)
    {
        if (data == JA_Head) //协议头
        {
            tcb->command_buf[tcb->parse_pointer++] = data;
        }
    }
    else if (tcb->parse_pointer == 1)
    {
        tcb->protocol.CS_Vsersion = data; //协议版本
        tcb->command_buf[tcb->parse_pointer++] = data;
    }
    else if (tcb->parse_pointer == 2)
    {
        tcb->protocol.Payload_len = data; //协议长度
        tcb->command_buf[tcb->parse_pointer++] = data;
    }
    else if (tcb->parse_pointer == 3) //协议地址
    {
        tcb->protocol.Address = data;
        tcb->command_buf[tcb->parse_pointer++] = data;
    }
    else if (tcb->parse_pointer == 4)
    {
        tcb->protocol.SN = data; //SN
        tcb->command_buf[tcb->parse_pointer++] = data;
    }
    else
    {
        tcb->command_buf[tcb->parse_pointer++] = data;
        if (tcb->parse_pointer == tcb->protocol.Payload_len + 7)
        {
            tcb->parse_pointer = 0;
            tcb->CRC_value = tcb->command_buf[tcb->protocol.Payload_len + 6];
            tcb->CRC_value = (tcb->CRC_value << 8) | tcb->command_buf[tcb->protocol.Payload_len + 5];
            if (tcb->CRC_value == CRC_16(tcb->command_buf, tcb->protocol.Payload_len + 5))
            {
                tcb->protocol.data.Opcode = tcb->command_buf[5];
                tcb->protocol.data.data_len = tcb->protocol.Payload_len - 1;
                tcb->protocol.data.data = tcb->command_buf + 6;
                r_buf = tcb->Parse(tcb->protocol, tcb->command_buf); //命令解析
                reply_buf->bytes = r_buf.bytes;
                reply_buf->len = r_buf.len;
                return JA_Decode_OK;
            }
            else
            {
                return JA_CRC_Fail;
                //CRC 校验失败
            }
        }
    }
    return JA_Decode_Proceed;
}
/******************************************
 * 功能：JA解码数据
 * 参数：
 *         tcb:JA 协议解析控制块
 *         *data:数据指针
 *         len：数据长度
 * 返回：无
 * ***************************************/
JA_BytesArray JA_Decode_Array(JA_Protocol_TCB *tcb, uint8_t *data, uint16_t len)
{
    uint16_t i = 0;
    JA_BytesArray reply_buf;
    JA_StatusTypeDef res;
    tcb->parse_pointer = 0;
    for (i = 0; i < len; i++)
    {
        res = JA_Decode(tcb, data[i], &reply_buf);
        if (res == JA_Decode_OK)
        {
            return reply_buf;
        }
        else if (res == JA_CRC_Fail)
        {
            reply_buf.len = 0;
        }
    }
    return reply_buf;
}
/********************************************
 * 功能：JA协议封装数据
 * 参数：
 *         tcb：JA协议
 *         *bytes：转为字节数组
 * 返回：无
 * *****************************************/
uint16_t JA_Package(JA_Protocol protocol, uint8_t *bytes)
{
    uint16_t len = 0;
    uint16_t crc = 0;
    len = protocol.data.data_len + 1;
    bytes[0] = 0xAA;
    bytes[1] = 0x01; //协议版本
    protocol.Payload_len = len;
    bytes[2] = protocol.Payload_len;
    bytes[3] = protocol.Address;
    bytes[4] = protocol.SN;
    bytes[5] = protocol.data.Opcode;
    mymemcpy(bytes + 6, protocol.data.data, protocol.data.data_len);
    crc = CRC_16(bytes, protocol.Payload_len + 5);
    bytes[protocol.Payload_len + 5] = (uint8_t)crc;
    bytes[protocol.Payload_len + 6] = (uint8_t)(crc >> 8);
    len = len + 7;
    return len;
}
